﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using System.Drawing.Design;
using System.Data;
using DevExpress.XtraBars;
using System.Windows.Forms;
using DevExpress.XtraGrid;
using DevExpress.XtraEditors.DXErrorProvider;
using ProgNetComponentsDx.Base.Components;
using ProgNetComponentsDx.Design;
using ProgNetComponentsDx.Mode.Design;
using ProgNetComponentsDx.Enums;
using ProgNetComponentsDx.Base.Interfaces;
using DevExpress.XtraEditors.Repository;
using DevExpress.LookAndFeel;

namespace ProgNetComponentsDx.Mode
{
    [Designer(typeof(DxGridColumnDesigner))]
    public class ModeProvider : BaseExtenderProvider<Mode.FormModeSettings>
    {
        public event EventHandler OnRefreshAll;

        private void Init()
        {
            FullValidationError = "Pole '{0}' jest wymagane";
            GridInvalidDataError = "Nie wszystkie wartości są poprawne";
            System.AppearanceObjectExt.SetStyleEvents();
            UserLookAndFeel.Default.StyleChanged += new EventHandler(Default_StyleChanged);
            System.AppearanceObjectExt.ErrorApperanceChanged += new EventHandler(Default_StyleChanged);
            System.AppearanceObjectExt.ReadOnlyApperanceChanged += new EventHandler(Default_StyleChanged);
            System.AppearanceObjectExt.RequiredApperanceChanged += new EventHandler(Default_StyleChanged);
        }
       
        void _ControllerModeProvider_OnRefreshAll(object sender, EventArgs e)
        {
            RefreshAll();
        }

        void _ControllerModeProvider_CurrentModeChanged(object sender, EventArgs e)
        {
            CurrentMode = ControllerModeProvider.CurrentMode;
        }

        void Default_StyleChanged(object sender, EventArgs e)
        {
            if (!this.IsDesignMode())
                RefreshAll();
        }

        public ModeProvider()
        {
            Init();
        }

        public ModeProvider(IContainer container)
            : base(container)
        {
            Init();
        }

        #region members
        private ModeProvider _ControllerModeProvider;
       
        private FormMode _CurrentMode = FormMode.None;
        private List<GridView> _Views = new List<GridView>();
        #endregion

        #region events
        public event EventHandler CurrentModeChanged;
        public event EventHandler<CustomModeSettingsEventArgs> CustomGetModes;
        public event DeleteRowHandler DeleteRow;
        private void OnDeleleteRow(object sender, DeleteRowEventArgs e)
        {
            if (DeleteRow != null)
            {
                DeleteRow(sender, e);
            }
        }

        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets ModeProvider that will control CurrentMode
        /// </summary>
        public ModeProvider ControllerModeProvider
        {
            get { return _ControllerModeProvider; }
            set
            {
                ModeProvider c = value;
                if (c != null)
                {
                    while (c != null)
                    {
                        if (c == this)
                            throw new Exception("ModeProvider Loop Detected.");
                        c = c.ControllerModeProvider;
                    }
                }
                if (!this.IsDesignMode() && _ControllerModeProvider != null)
                {
                    _ControllerModeProvider.CurrentModeChanged -= new EventHandler(_ControllerModeProvider_CurrentModeChanged);
                    _ControllerModeProvider.OnRefreshAll -= new EventHandler(_ControllerModeProvider_OnRefreshAll);
                }

                _ControllerModeProvider = value;

                if (!this.IsDesignMode() && _ControllerModeProvider != null)
                {
                    _ControllerModeProvider.CurrentModeChanged += new EventHandler(_ControllerModeProvider_CurrentModeChanged);
                    _ControllerModeProvider.OnRefreshAll += new EventHandler(_ControllerModeProvider_OnRefreshAll);
                    this.CurrentMode = _ControllerModeProvider.CurrentMode;
                }
            }
        }

        public string FullValidationError
        {
            get;
            set;
        }
        [Editor(typeof(FormModeUIEditor), typeof(UITypeEditor))]
        public FormMode CurrentMode
        {
            get { return _CurrentMode; }
            set
            {
                if (_CurrentMode != value)
                {
                    _CurrentMode = value;
                    if (!IsInitializing)
                    {
                        List<GridControl> grids = new List<GridControl>();
                            foreach (GridView v in _Views)
                            {
                                if (v.GridControl != null)
                                {
                                    if (!grids.Contains(v.GridControl))
                                    {
                                        grids.Add(v.GridControl);
                                    }
                                }
                            }
                            foreach (GridControl g in grids)
                            {
                                g.CollapseAllDetails();
                            }
                        OnCurrentModeChanged();
                    }
                }
            }
        }

        public string GridInvalidDataError
        {
            get;
            set;
        }
        public DXErrorProvider ErrorProvider
        {
            get;
            set;
        }
        public bool SetErrorAppearance
        {
            get;
            set;
        }
        #endregion

        #region Override
        public override void RefreshAll()
        {
            base.RefreshAll();
            if (OnRefreshAll != null)
                OnRefreshAll(this, EventArgs.Empty);
        }

        protected override void ProcessObject(object target, FormModeSettings settings)
        {
            if (settings != null)
            {
                if (target is GridColumn)
                {
                    ProcessGridColumn(target as GridColumn);
                }
                else if (target is BaseEdit)
                {
                    BaseEdit ed = target as BaseEdit;
                    ProcessBaseEdit(ed);
                }
                else if (target is GridView)
                {
                    GridView gv = target as GridView;
                    ProcessGridView(gv);
                }
                else if (target is BarItem)
                {
                    ProcessBarItem(target as BarItem);
                }
                else if (target is IReadOnlyControl)
                {
                    ProcessIReadOnlyControl(target as IReadOnlyControl);
                }
                else if (target is Control)
                {
                    ProcessControl(target as Control);
                }
            }
        }

        protected override FormModeSettings CreateSettings(object target)
        {
            FormModeSettings settings = new FormModeSettings(target, this);
            if (!IsReadOnlyByDefault(target))
                settings.ReadOnlyModes = FormMode.None;

            return settings;
        }
        private bool IsReadOnlyByDefault(object target)
        {
            if (target is GridColumn ||
               target is BaseEdit ||
               target is GridView ||
               target is SimpleButton ||
               target is BarItem ||
                target is IReadOnlyControl)
                return true;
            return false;
        }

        public override bool CanExtend(object extendee)
        {
            if (extendee is GridColumn ||
                extendee is BaseEdit ||
                extendee is GridView ||
                extendee is SimpleButton ||
                extendee is BarItem ||
                extendee is IReadOnlyControl)
                return true;
            if (extendee is Form |
                extendee is Label ||
                extendee is LabelControl ||
                extendee is GridControl)
                return false;
            if (extendee is Control)
                return true;
            return false;
        }

        protected override object GetRealKey(object target)
        {
            object key = target;

            if (target is GridColumn)
            {
                ColumnView cv = (target as GridColumn).View as ColumnView;

                if (cv != null && cv.SourceView != null && cv.SourceView is ColumnView)
                {
                    cv = cv.SourceView as ColumnView;
                    try
                    {
                        key = cv.Columns.ColumnByName((target as GridColumn).Name);
                    }
                    catch { }
                }
            }
            if (target is BaseView)
            {
                BaseView gv = target as BaseView;
                if (gv.SourceView != null)
                    key = gv.SourceView;
            }
            return key;
        }

        #endregion

        #region private methods
        private void settings_SettingsChanged(object sender, EventArgs e)
        {
            ProcessObject(sender);
        }

        private void OnCurrentModeChanged()
        {
                if (CurrentModeChanged != null)
                    CurrentModeChanged(this, EventArgs.Empty);
                foreach (KeyValuePair<object, FormModeSettings> kvp in AllObjects)
                {
                    RemoveKeyFromChanged(kvp.Key);
                    ProcessObject(kvp.Key, kvp.Value);
                }
            }

        private void OnCustomGetModes(object target, CustomModeSettingsEventArgs e)
        {
            if (CustomGetModes != null)
            {
                CustomGetModes(target, e);
            }
        }

        private void gv_ShowingEditor(object sender, CancelEventArgs e)
        {
            GridView gv = (sender as GridView);
            UpdateColumn(gv, gv.FocusedColumn, gv.FocusedRowHandle);
        }
        private void UpdateColumn(GridView gv, GridColumn col, int rowHandle)
        {
            if (gv != null && col!=null)
            {
                CustomModeSettingsEventArgs ce = GetViewArgs(col, rowHandle);
                if (ce != null)
                {
                    OnCustomGetModes(col, ce);
                    gv.FocusedColumn.OptionsColumn.ReadOnly = ce.IsReadOnly;
                    gv.FocusedColumn.OptionsColumn.AllowEdit = !(ce.IsReadOnly && ce.IsFullReadOnly);
                }
            }
        }
        private void gv_RowCellStyle(object sender, RowCellStyleEventArgs e)
        {
            GridView gv = (sender as GridView);
            if (gv != null)
            {
                if(gv.IsRowSelected(e.RowHandle))
                    return;
                
                CustomModeSettingsEventArgs ce = GetViewArgs(e.Column, e.RowHandle);
                if (ce != null)
                {
                    OnCustomGetModes(e.Column, ce);

                    if (SetErrorAppearance && e.Column.UnboundType == DevExpress.Data.UnboundColumnType.Bound)
                    {
                        DataRow r = gv.GetDataRow(e.RowHandle);
                        if (r != null && r.Table.Columns.Contains(e.Column.FieldName))
                        {
                            if (r.GetColumnError(e.Column.FieldName).IsNotNull())
                            {
                                e.Appearance.SetErrorAppearance();
                                return;
                            }
                        }
                    }

                    if (ce.IsReadOnly)
                        e.Appearance.SetReadOnlyAppearance();
                    else if (ce.IsRequired)
                        e.Appearance.SetRequiredAppearance();
                }
            }
        }

        private CustomModeSettingsEventArgs GetViewArgs(GridColumn col, int rowHandle)
        {
            CustomModeSettingsEventArgs ce = null;
            object key = GetRealKey(col);
            if (this.AllObjects.ContainsKey(key))
            {
                FormModeSettings settings = AllObjects[key];
                FormModeSettings viewSettings = null;
                object realView = GetRealKey(col.View);
                if (AllObjects.ContainsKey(realView))
                {
                    viewSettings = AllObjects[realView];
                }
                if (settings != null)
                {
                    FormMode m = CurrentMode;
                    if (viewSettings != null && viewSettings.TreatNewRecordAsNewMode)
                    {
                        DataRow r = col.View.GetDataRow(rowHandle);
                        if (r == null || r.RowState == DataRowState.Added)
                            m = FormMode.New;
                    }

                    bool isReadOnly = (settings.ReadOnlyModes & m) != FormMode.None;
                    bool isReq = (settings.RequiredModes & m) != FormMode.None;
                    if (rowHandle == DevExpress.XtraGrid.GridControl.AutoFilterRowHandle)
                        isReadOnly = isReq = false;
                    ce = new CustomModeSettingsEventArgs(isReadOnly, isReq, settings.FullReadOnly, col.View.GetDataRow(rowHandle));
                }
            }
            return ce;
        }

        private CustomModeSettingsEventArgs GetViewArgs(GridColumn col, DataRow r)
        {
            CustomModeSettingsEventArgs ce = null;
            object key = GetRealKey(col);
            if (this.AllObjects.ContainsKey(key))
            {
                FormModeSettings settings = AllObjects[key];
                FormModeSettings viewSettings = null;
                object realView = GetRealKey(col.View);
                if (AllObjects.ContainsKey(realView))
                {
                    viewSettings = AllObjects[realView];
                }
                if (settings != null)
                {
                    FormMode m = CurrentMode;
                    if (viewSettings != null && viewSettings.TreatNewRecordAsNewMode)
                    {
                        if (r == null || r.RowState == DataRowState.Added)
                            m = FormMode.New;
                    }

                    bool isReadOnly = (settings.ReadOnlyModes & m) != FormMode.None;
                    bool isReq = (settings.RequiredModes & m) != FormMode.None;
                   
                    ce = new CustomModeSettingsEventArgs(isReadOnly, isReq, settings.FullReadOnly, r);
                }
            }
            return ce;
        }
        private CustomModeSettingsEventArgs GetStandardsettings(object target)
        {
            CustomModeSettingsEventArgs ce = null;
            target = GetRealKey(target);
            if (target != null)
            {
                if (AllObjects.ContainsKey(target))
                {
                    FormModeSettings settings = AllObjects[target];
                    if (settings != null)
                    {
                        bool isReadOnly = (settings.ReadOnlyModes & CurrentMode) != FormMode.None;
                        bool isReq = (settings.RequiredModes & CurrentMode) != FormMode.None;
                        ce = new CustomModeSettingsEventArgs(isReadOnly, isReq, settings.FullReadOnly);
                    }
                }
            }
            return ce;
        }

        #endregion

        #region Processing objects

        private void SaveAppearance(object control)
        {
            FormModeSettings s = GetSettings(control);
            if (control is BaseStyleControl)
            {
                if (s != null && s.DefaultAppearance == null)
                {
                    s.SetDefaultAppearance((control as BaseStyleControl).Appearance);
                }
            }
            else if (control is RepositoryItem)
            {
                if (s != null && s.DefaultAppearance == null)
                {
                    s.SetDefaultAppearance((control as RepositoryItem).Appearance);
                }
            }
            else if (control is BaseEdit)
            {
                if (s != null && s.DefaultAppearance == null)
                {
                    s.SetDefaultAppearance((control as BaseEdit).Properties.Appearance);
                }
            }
        }
        private void RestoreAppearance(object control)
        {
            FormModeSettings s = GetSettings(control);
            if (control is BaseStyleControl)
            {
                if (s != null && s.DefaultAppearance != null)
                    (control as BaseStyleControl).Appearance.Assign(s.DefaultAppearance);
                else
                    (control as BaseStyleControl).Appearance.Reset();
            }
            else if (control is RepositoryItem)
            {
                if (s != null && s.DefaultAppearance != null)
                    (control as RepositoryItem).Appearance.Assign(s.DefaultAppearance);
                else
                    (control as RepositoryItem).Appearance.Reset();
            }
            else if (control is BaseEdit)
            {
                if (s != null && s.DefaultAppearance != null)
                    (control as BaseEdit).Properties.Appearance.Assign(s.DefaultAppearance);
                else
                    (control as BaseEdit).Properties.Appearance.Reset();
            }
        }
        private void ProcessBarItem(BarItem barItem)
        {
            if (barItem is BarSubItem)
                return;
            CustomModeSettingsEventArgs ce = GetStandardsettings(barItem);
            if (ce != null)
            {
                OnCustomGetModes(barItem, ce);
                barItem.Enabled = !ce.IsReadOnly;
            }
        }

        private void ProcessControl(Control control)
        {
            CustomModeSettingsEventArgs ce = GetStandardsettings(control);
            if (ce != null)
            {
                SaveAppearance(control);
                OnCustomGetModes(control, ce);
                control.Enabled = !ce.IsReadOnly; 
                if (!this.IsDesignMode())
                {
                    if (control is BaseStyleControl)
                    {
                        if (ErrorProvider != null && SetErrorAppearance && ErrorProvider.GetError(control).IsNotNull())
                        {
                            ((BaseStyleControl)control).Appearance.SetErrorAppearance();
                            return;
                        }
                        if (ce.IsReadOnly)
                            (control as BaseStyleControl).Appearance.SetReadOnlyAppearance();
                        else
                        {
                            RestoreAppearance(control);
                        }
                    }
                }
            }
        }
        private void ProcessIReadOnlyControl(IReadOnlyControl control)
        {
            CustomModeSettingsEventArgs ce = GetStandardsettings(control);
            if (ce != null)
            {
                SaveAppearance(control);
                OnCustomGetModes(control, ce);
                control.ReadOnly = ce.IsReadOnly;
                if (!this.IsDesignMode())
                {
                    if (control is BaseStyleControl)
                    {
                        if (ce.IsReadOnly)
                            (control as BaseStyleControl).Appearance.SetReadOnlyAppearance();
                        else
                        {
                            RestoreAppearance(control);
                        }
                    }
                }
            }
        }
        private void ProcessBaseEdit(BaseEdit ed)
        {
            CustomModeSettingsEventArgs ce = GetStandardsettings(ed);
            if (ce != null)
            {
                SaveAppearance(ed);
                OnCustomGetModes(ed, ce);
                ed.Properties.ReadOnly = ce.IsReadOnly;
                if (!this.IsDesignMode())
                {
                    if (ErrorProvider != null && SetErrorAppearance && ErrorProvider.GetError(ed).IsNotNull())
                    {
                        ed.Properties.Appearance.SetErrorAppearance();
                        return;
                    }
                    if (ce.IsReadOnly)
                        ed.Properties.Appearance.SetReadOnlyAppearance();
                    else if (ce.IsRequired)
                        ed.Properties.Appearance.SetRequiredAppearance();
                    else
                        RestoreAppearance(ed);
                }
            }
        }

        private void ProcessGridColumn(GridColumn col)
        {
            if (col != null)
            {
                GridView gv = col.View as GridView;
                if (gv != null)
                {
                    if (gv.SourceView != null && gv.SourceView is GridView)
                    {
                        gv = gv.SourceView as GridView;
                    }
                    if (!_Views.Contains(gv))
                    {
                        _Views.Add(gv);
                        gv.RowCellStyle += new RowCellStyleEventHandler(gv_RowCellStyle);
                        gv.ShowingEditor += new CancelEventHandler(gv_ShowingEditor);
                        gv.FocusedRowChanged+=new FocusedRowChangedEventHandler(gv_FocusedRowChanged);
                        gv.FocusedColumnChanged += new FocusedColumnChangedEventHandler(gv_FocusedColumnChanged);
                    }
                    if (gv.GridControl != null)
                        gv.GridControl.Refresh();
                    gv.RefreshData();
                }
            }
        }

        private void ProcessGridView(GridView gv)
        {
            if (gv != null)
            {
                if (gv.SourceView != null && gv.SourceView is GridView)
                {
                    gv = gv.SourceView as GridView;
                }
                object key = GetRealKey(gv);
                if (key != null)
                {
                    if (AllObjects.ContainsKey(key))
                    {
                        FormModeSettings settings = AllObjects[key];
                        if (settings != null)
                        {
                            if ((settings.AllowNewRecordModes & CurrentMode) != FormMode.None)
                                gv.OptionsView.NewItemRowPosition = settings.NewItemRowPosition;
                            else
                                gv.OptionsView.NewItemRowPosition = NewItemRowPosition.None;

                                if (gv.GridControl != null)
                                {
                                    gv.GridControl.Refresh();
                                    gv.GridControl.FocusedViewChanged += new DevExpress.XtraGrid.ViewFocusEventHandler(GridControl_FocusedViewChanged);
                                }
                                gv.RefreshData();
                                gv.KeyDown -= new KeyEventHandler(gv_KeyDown);
                                gv.KeyDown += new KeyEventHandler(gv_KeyDown);
                                gv.FocusedRowChanged -= new FocusedRowChangedEventHandler(gv_FocusedRowChanged);
                                gv.FocusedRowChanged += new FocusedRowChangedEventHandler(gv_FocusedRowChanged);
                                gv.MasterRowExpanded -= new CustomMasterRowEventHandler(gv_MasterRowExpanded);
                                gv.MasterRowExpanded += new CustomMasterRowEventHandler(gv_MasterRowExpanded);
                            }
                        }
                    }
                }
            }

        void gv_MasterRowExpanded(object sender, CustomMasterRowEventArgs e)
        {
            GridView parent = (sender as GridView);
            if (parent != null)
            {
                GridView gv = parent.GetDetailView(e.RowHandle, e.RelationIndex) as GridView;
                if (gv != null)
                    RefreshGridNewItemRowPos(gv);
            }
        }

        void GridControl_FocusedViewChanged(object sender, DevExpress.XtraGrid.ViewFocusEventArgs e)
        {
            RefreshGridNewItemRowPos(e.View as GridView);
        }
        private void RefreshGridNewItemRowPos(GridView gv)
        {
            object key = GetRealKey(gv);
            if (key != null)
            {
                if (AllObjects.ContainsKey(key))
                {
                    FormModeSettings settings = AllObjects[key];
                    if (settings != null)
                    {
                        NewItemRowPosition pos = NewItemRowPosition.None;
                        if (settings.NewItemRowPosition != pos &&
                            gv.SourceRow != null && gv.SourceRow is DataRowView)
                        {
                            DataRow r = (gv.SourceRow as DataRowView).Row;
                            FormMode m = CurrentMode;
                            if (r != null)
                            {
                                if (r.RowState == DataRowState.Added)
                                {
                                    m = FormMode.New;
                                }
                            }
                            if ((settings.AllowNewRecordModes & m) != FormMode.None)
                            {
                                pos = settings.NewItemRowPosition;
                            }
                            gv.OptionsView.NewItemRowPosition = pos;
                        }
                    }
                }
            }
        }

        void gv_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
        {
             GridView gv = (sender as GridView);
             if (gv != null)
             {
                 RefreshGridNewItemRowPos(gv);
                 UpdateColumn(gv, gv.FocusedColumn, e.PrevFocusedRowHandle);
                 UpdateColumn(gv, gv.FocusedColumn, e.FocusedRowHandle);
             }

        }
        void gv_FocusedColumnChanged(object sender, FocusedColumnChangedEventArgs e)
        {
             GridView gv = (sender as GridView);
             if (gv != null)
             {
                 UpdateColumn(gv, e.PrevFocusedColumn, gv.FocusedRowHandle);
                 UpdateColumn(gv, e.FocusedColumn, gv.FocusedRowHandle);
             }
        }
        void gv_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                GridView gv = sender as GridView;
                object key = GetRealKey(gv);
                FormModeSettings settings = null;
                if (AllObjects.ContainsKey(key))
                {
                    settings = AllObjects[key];
                }
                if (settings != null)
                {
                    FormMode m = CurrentMode;
                    DataRow[] rows = gv.GetSelectedDataRows();
                    if (rows.Length > 0)
                    {
                        if (gv != key)
                        {
                            DataRow parentRow = rows[0].GetParentRow(gv.GridControl.LevelTree.Find(gv.SourceView).RelationName);
                            if (parentRow != null && parentRow.RowState == DataRowState.Added)
                            {
                                if (gv.GridControl.LevelTree.Find(gv.SourceView).Parent.LevelTemplate != null)
                                {
                                    key = GetRealKey(gv.GridControl.LevelTree.Find(gv.SourceView).Parent.LevelTemplate);
                                    if (key != null)
                                    {
                                        if (AllObjects.ContainsKey(key))
                                        {
                                            if (AllObjects[key].TreatNewRecordAsNewMode)
                                            {
                                                m = FormMode.New;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        DeleteRowEventArgs ea = new DeleteRowEventArgs(null);
                        foreach (DataRow r in rows)
                        {
                            if ((settings.AllowDeleteModes & m) != FormMode.None)
                            {
                                ea.Cancel = false;
                                ea.Row = r;
                                OnDeleleteRow(sender, ea);
                                if (!ea.Cancel)
                                    r.Delete();
                            }
                        }
                    }
                }
            }
        }
        #endregion

        public bool ValidateRequiredEdits(ref string errorMessage)
        {
            bool result = true;
                foreach (KeyValuePair<object, FormModeSettings> kvp in AllObjects)
                {
                    if (kvp.Key is BaseEdit)
                    {
                        CustomModeSettingsEventArgs ce = GetStandardsettings(kvp.Key);
                        if (ce != null)
                        {
                            OnCustomGetModes(kvp.Key, ce);
                            if (ce.IsRequired)
                            {
                                if ((kvp.Key as BaseEdit).EditValue.IsNull())
                                {
                                    result = false;
                                    string line = kvp.Value.ValidationSettings.GetFormatedError();
                                    if (ErrorProvider != null)
                                    {
                                        ErrorProvider.SetError((kvp.Key as BaseEdit), line);
                                    }
                                    errorMessage = errorMessage.AppendLine(line);
                                }
                            }
                        }
                    }
            }
            return result;
        }
        public bool ValidateRequiredEdits(IEnumerable<BaseEdit> edits, ref string errorMessage)
        {
            bool result = true;
            object key;
            FormModeSettings settings;
            foreach (BaseEdit edit in edits)
            {
                key = GetRealKey(edit);
                if (AllObjects.ContainsKey(key))
                    settings = AllObjects[key];
                else
                    continue;
                    CustomModeSettingsEventArgs ce = GetStandardsettings(key);
                    if (ce != null)
                    {
                        OnCustomGetModes(edit, ce);
                        if (ce.IsRequired)
                        {
                            if (edit.EditValue.IsNull())
                            {
                                result = false;
                                string line = settings.ValidationSettings.GetFormatedError();
                                if (ErrorProvider != null)
                                {
                                    ErrorProvider.SetError(edit, line);
                                }
                                errorMessage = errorMessage.AppendLine(line);
                            }
                        }
                    }
            }
            return result;
        }
        public bool ValidateRequiredEdit(BaseEdit edit, ref string errorMessage)
        {
            return ValidateRequiredEdits(new BaseEdit[] { edit }, ref errorMessage);
        }
        public bool ValidateRequiredColumns(ref string errorMessage)
        {
            bool result = true;
            DateTime d = DateTime.Now;
            TimeSpan ts;
            CustomModeSettingsEventArgs e = null;
            List<string> errors = new List<string>();
            foreach (KeyValuePair<object, FormModeSettings> kvp in AllObjects)
            {
                if (kvp.Key is GridColumn)
                {
                    GridColumn col = kvp.Key as GridColumn;
                    if (col.UnboundType != DevExpress.Data.UnboundColumnType.Bound)
                        continue;
                    
                    DataTable dt = null;
                    if (col.View !=null && col.View.DataSource is DataView)
                    {
                        dt = (col.View.DataSource as DataView).Table;
                    }
                    else if (col.View != null && col.View.GridControl !=null)
                    {
                        GridLevelNode node = col.View.GridControl.LevelTree.Find(col.View);
                        if (node != null && node.RelationName.IsNotNull())
                        {
                            DataSet ds = null;
                            if (col.View.GridControl.DataSource is DataSet)
                                ds = (col.View.GridControl.DataSource as DataSet);
                            else if(col.View.GridControl.DataSource is BindingSource)
                                ds = (col.View.GridControl.DataSource as BindingSource).DataSource as DataSet;

                            if (ds != null && ds.Relations.Contains(node.RelationName))
                            {
                                dt = ds.Relations[node.RelationName].ChildTable;
                            }
                        }
                    }
                    if (dt != null)
                    {
                        foreach (DataRow r in dt.Rows)
                        {
                            if (r.CanRead())
                            {
                                e = GetViewArgs(col, r);
                                OnCustomGetModes(col, e);
                                if (e.IsRequired)
                                {
                                    if (r[col.FieldName].IsNull())
                                    {
                                        r.ExpandParentNode(col.View);
                                        result = false;
                                        string line = kvp.Value.ValidationSettings.GetFormatedError();
                                        r.SetColumnError(col.FieldName, line);
                                        if (ErrorProvider != null)
                                            ErrorProvider.SetError(col.View.GridControl, this.GridInvalidDataError);
                                        if (!errors.Contains(line))
                                            errors.Add(line);
                                    }
                                    else
                                    {
                                        r.SetColumnError(col.FieldName, "");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (string s in errors)
                errorMessage = errorMessage.AppendLine(s);
            ts = DateTime.Now - d;
            return result;
        }
        public bool ValidateRequiredColumns(IEnumerable<GridColumn>  columns, ref string errorMessage)
        {
            bool result = true;
            DateTime d = DateTime.Now;
            TimeSpan ts;
            CustomModeSettingsEventArgs e = null;
            List<string> errors = new List<string>();
            if (columns != null)
            {
                GridColumn col;
                FormModeSettings settings;
                object key;
                foreach (GridColumn c in columns)
                {
                    settings = null;
                    key = GetRealKey(c);
                    if (AllObjects.ContainsKey(key))
                        settings = AllObjects[key];
                    else
                        continue;

                    col = GetRealKey(c) as GridColumn;
                    if (col == null || col.UnboundType != DevExpress.Data.UnboundColumnType.Bound)
                        continue;

                    DataTable dt = null;
                    if (col.View != null && col.View.DataSource is DataView)
                    {
                        dt = (col.View.DataSource as DataView).Table;
                    }
                    else if (col.View != null && col.View.GridControl != null)
                    {
                        GridLevelNode node = col.View.GridControl.LevelTree.Find(col.View);
                        if (node != null && node.RelationName.IsNotNull())
                        {
                            DataSet ds = null;
                            if (col.View.GridControl.DataSource is DataSet)
                                ds = (col.View.GridControl.DataSource as DataSet);
                            else if (col.View.GridControl.DataSource is BindingSource)
                                ds = (col.View.GridControl.DataSource as BindingSource).DataSource as DataSet;

                            if (ds != null && ds.Relations.Contains(node.RelationName))
                            {
                                dt = ds.Relations[node.RelationName].ChildTable;
                            }
                        }
                    }
                    if (dt != null)
                    {
                        foreach (DataRow r in dt.Rows)
                        {
                            if (r.CanRead())
                            {
                                e = GetViewArgs(col, r);
                                OnCustomGetModes(col, e);
                                if (e.IsRequired)
                                {
                                    if (r[col.FieldName].IsNull())
                                    {
                                        r.ExpandParentNode(col.View);
                                        result = false;
                                        string line = settings.ValidationSettings.GetFormatedError();
                                        r.SetColumnError(col.FieldName, line);
                                        if (ErrorProvider != null)
                                            ErrorProvider.SetError(col.View.GridControl, this.GridInvalidDataError);
                                        if (!errors.Contains(line))
                                            errors.Add(line);
                                    }
                                    else
                                    {
                                        r.SetColumnError(col.FieldName, "");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (string s in errors)
                errorMessage = errorMessage.AppendLine(s);
            ts = DateTime.Now - d;
            return result;
        }
        public bool ValidateRequiredColumn(GridColumn column, ref string errorMessage)
        {
            return ValidateRequiredColumns(new GridColumn[] { column }, ref errorMessage);
        }
        public bool ValidateRequiredColumns(IEnumerable<GridView> views, ref string errorMessage)
        {
            List<GridColumn> cols = new List<GridColumn>();
            if (views != null)
            {
                foreach (GridView v in views)
                {
                    foreach (GridColumn c in v.Columns)
                    {
                        cols.AddIfNotExist(c);
                    }
                }
            }
            return ValidateRequiredColumns(cols, ref errorMessage);
        }
        public bool ValidateRequiredColumns(GridView view, ref string errorMessage)
        {
            return ValidateRequiredColumns(new GridView[] { view }, ref errorMessage);
        }
    }

    public class CustomModeSettingsEventArgs : EventArgs
    {
        private DataRow _Row;
        public DataRow Row
        {
            get { return _Row; }
        }

        public bool IsReadOnly
        {
            get;
            set;
        }
        public bool IsRequired
        {
            get;
            set;
        }
        public bool IsFullReadOnly
        {
            get;
            set;
        }
        public CustomModeSettingsEventArgs(bool isReadOnly, bool isRequired, bool IsFullReadOnly, DataRow row = null)
        {
            this.IsReadOnly = isReadOnly;
            this.IsRequired = isRequired;
            this.IsFullReadOnly = IsFullReadOnly;
            this._Row = row;
        }
        
    }

    public delegate void DeleteRowHandler(object sender, DeleteRowEventArgs e);
    public class DeleteRowEventArgs : CancelEventArgs
    {
        public DataRow Row
        {
            get;
            internal set;
        }

        public DeleteRowEventArgs(DataRow row)
        {
            Row = row;
        }

    }
}
